﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Xml.Linq;
using System.Xml.XPath;

namespace UtilZ.Dotnet.Ex.Log
{
    /// <summary>
    /// 日志记录器
    /// </summary>
    public class Loger
    {
        #region 初始化
        private static readonly ILogerCore _emptyLogerCore;
        private static ILogerCore _defaultLogerCore;

        /// <summary>
        /// [key:LogerName;Value:ILogerCore]
        /// </summary>
        private static readonly ConcurrentDictionary<string, ILogerCore> _logerCoreDic = new ConcurrentDictionary<string, ILogerCore>();

        /// <summary>
        /// 静态构造函数(初始化默认日志追加器)
        /// </summary>
        static Loger()
        {
            _emptyLogerCore = new EmptyLogerCore();
            if (File.Exists(LogConstant.DEFAULT_CONFIG_FILE_NAME))
            {
                try
                {
                    var xdoc = XDocument.Load(LogConstant.DEFAULT_CONFIG_FILE_NAME);
                    PrimitiveLoadConfig(xdoc);
                    return;
                }
                catch (Exception ex)
                {
                    LogSysInnerLog.OnRaiseLog("加载配置文件异常,使用默认日志配置.", ex);
                }
            }

            ILogerCore defaultLoger = new LogerCore(false);
            defaultLoger.AddAppender(new FileAppender(new FileAppenderConfig(null)));
            _defaultLogerCore = defaultLoger;
        }



        /// <summary>
        /// 加载配置,加载前清空旧的配置
        /// </summary>
        /// <param name="configFilePath">配置文件路径</param>
        public static void LoadConfig(string configFilePath)
        {
            if (!File.Exists(configFilePath))
            {
                return;
            }

            try
            {
                var xdoc = XDocument.Load(configFilePath);
                PrimitiveLoadConfig(xdoc);
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog("加载配置文件异常", ex);
            }
        }

        /// <summary>
        /// 加载配置,加载前清空旧的配置
        /// </summary>
        /// <param name="xdoc">配置文件xml</param>
        public static void LoadConfig(XDocument xdoc)
        {
            if (xdoc == null)
            {
                return;
            }

            try
            {
                PrimitiveLoadConfig(xdoc);
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog("加载配置文件异常", ex);

            }
        }

        /// <summary>
        /// 加载配置,加载前清空旧的配置
        /// </summary>
        /// <param name="xdoc">配置文件XDocument</param>
        private static bool PrimitiveLoadConfig(XDocument xdoc)
        {
            if (string.Equals(xdoc.Root.Name.LocalName, LogConstant.LOGCONFIG_ROOT_ELEMENT_NAME, StringComparison.OrdinalIgnoreCase))
            {
                var logerEles = xdoc.Root.Elements(LogConstant.LOGCONFIG_LOGER_ELEMENT_NAME);
                if (logerEles.Count() == 0)
                {
                    return false;
                }

                foreach (var logerEle in logerEles)
                {
                    ParseLogerConfig(logerEle);
                }

                return true;
            }
            else
            {
                LogSysInnerLog.OnRaiseLog("无效的载配置文件", null);
                return false;
            }
        }

        private static void ParseLogerConfig(XElement logerEle)
        {
            try
            {
                string name = LogUtil.GetAttributeValue(logerEle, "name");
                if (string.IsNullOrEmpty(name))
                {
                    if (_defaultLogerCore != _emptyLogerCore && _defaultLogerCore != null)
                    {
                        _defaultLogerCore.Dispose();
                    }

                    _defaultLogerCore = _emptyLogerCore;
                }

                bool asynOutput;
                if (!bool.TryParse(LogUtil.GetAttributeValue(logerEle, "asynOutput"), out asynOutput))
                {
                    asynOutput = false;
                }

                ILogerCore logerCore = new LogerCore(asynOutput);
                logerCore.Name = name;

                LogLevel level;
                if (Enum.TryParse<LogLevel>(LogUtil.GetAttributeValue(logerEle, "level"), true, out level))
                {
                    logerCore.Level = level;
                }

                bool enable;
                if (bool.TryParse(LogUtil.GetAttributeValue(logerEle, "enable"), out enable))
                {
                    logerCore.Enable = enable;
                }

                string outputStackLevels = LogUtil.GetAttributeValue(logerEle, "outputStackLevels");
                if (!string.IsNullOrWhiteSpace(outputStackLevels))
                {
                    string[] outputStackLevelArr = outputStackLevels.Split(new char[] { ',', '，', '|' }, StringSplitOptions.RemoveEmptyEntries);
                    List<LogLevel> logLevels = new List<LogLevel>();
                    LogLevel tmpLogLevel;
                    for (int i = 0; i < outputStackLevelArr.Length; i++)
                    {
                        if (Enum.TryParse<LogLevel>(outputStackLevelArr[i].Trim(), out tmpLogLevel))
                        {
                            logLevels.Add(tmpLogLevel);
                        }
                    }

                    logerCore.OutputStackLevels = logLevels.ToArray();
                }

                IEnumerable<XElement> appenderEles = logerEle.XPathSelectElements("appender");
                foreach (var appenderEle in appenderEles)
                {
                    try
                    {
                        CreateAppender(appenderEle, logerCore);
                    }
                    catch (Exception exi)
                    {
                        LogSysInnerLog.OnRaiseLog(null, exi);
                    }
                }

                if (string.IsNullOrEmpty(name))
                {
                    _defaultLogerCore = logerCore;
                }
                else
                {
                    _logerCoreDic.AddOrUpdate(name, logerCore, (key, oldValue) =>
                    {
                        oldValue.Dispose();
                        return logerCore;
                    });
                }
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog("解析配置文件异常", ex);
            }
        }

        private static void CreateAppender(XElement appenderEle, ILogerCore logerCore)
        {
            string appenderName = LogUtil.GetAttributeValue(appenderEle, "name");
            try
            {
                string appenderTypeName = LogUtil.GetAttributeValue(appenderEle, "type");
                if (string.IsNullOrWhiteSpace(appenderTypeName))
                {
                    return;
                }

                appenderTypeName = appenderTypeName.Trim();
                IAppender appender = CreateAppenderByAppenderPattern(appenderTypeName, appenderEle);
                if (appender == null)
                {
                    return;
                }

                appender.Name = appenderName;
                logerCore.AddAppender(appender);
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog(string.Format("解析:{0}日志追加器异常", appenderName), ex);
            }
        }

        private static IAppender CreateAppenderByAppenderPattern(string appenderTypeName, XElement appenderEle)
        {
            IAppender appender;
            switch (appenderTypeName.Trim().ToUpper())
            {
                case LogConstant.FILE_APPENDER_PATTERN_BREIF:
                case LogConstant.FILE_APPENDER_PATTERN:
                    appender = new FileAppender(appenderEle);
                    break;
                case LogConstant.REDIRECT_APPENDER_PATTERN_BREIF:
                case LogConstant.REDIRECT_APPENDER_PATTERN:
                    appender = new RedirectAppender(appenderEle);
                    break;
                case LogConstant.CONSOLE_APPENDER_PATTERN_BREIF:
                case LogConstant.CONSOLE_APPENDER_PATTERN:
                    appender = new ConsoleAppender(appenderEle);
                    break;
                case LogConstant.DATABASE_APPENDER_PATTERN_BREIF:
                case LogConstant.DATABASE_APPENDER_PATTERN:
                    appender = new DatabaseAppender(appenderEle);
                    break;
                case LogConstant.MAIL_APPENDER_PATTERN_BREIF:
                case LogConstant.MAIL_APPENDER_PATTERN:
                    appender = new MailAppender(appenderEle);
                    break;
                case LogConstant.SYSTEM_APPENDER_PATTERN_BREIF:
                case LogConstant.SYSTEM_APPENDER_PATTERN:
                    appender = new SystemLogAppender(appenderEle);
                    break;
                default:
                    appender = null;
                    break;
            }

            return appender;
        }

        #endregion




        #region public 方法
        /// <summary>
        /// 根据日志追加器名称获取指定日志记录器中的日志追加器
        /// </summary>
        /// <param name="logerName">日志记录器名称</param>
        /// <param name="appenderName">日志追加器名称</param>
        /// <returns>日志追加器</returns>
        public static IAppender GetAppenderByName(string logerName, string appenderName)
        {
            ILogerCore logerCore = GetLoger(logerName);
            if (logerCore == null)
            {
                return null;
            }

            return logerCore.GetAppenderByName(appenderName);
        }

        /// <summary>
        /// 获取指定日志记录器中的日志追加器
        /// </summary>
        /// <param name="logerName">日志记录器名称</param>
        /// <returns>日志追加器数组</returns>
        public static IAppender[] GetAppenders(string logerName)
        {
            ILogerCore logerCore = GetLoger(logerName);
            if (logerCore == null)
            {
                return null;
            }

            return logerCore.GetAppenders();
        }

        /// <summary>
        /// 获取日志记录器,如果日志记录器名称为空或null则返回默认日志记录器,否则当名称对应的日志记录器存在时返回配置的日志记录器,不存在则抛出异常
        /// </summary>
        /// <param name="logerName">日志记录器名称</param>
        /// <returns>日志记录器</returns>
        public static ILogerCore GetLoger(string logerName)
        {
            ILogerCore logerCore;
            if (string.IsNullOrEmpty(logerName))
            {
                logerCore = _defaultLogerCore;
            }
            else
            {
                if (_logerCoreDic.TryGetValue(logerName, out logerCore))
                {
                    return logerCore;
                }
                else
                {
                    throw new ApplicationException($"不存在名称为\"{logerName}\"的日志记录器");
                }
            }

            if (logerCore == null)
            {
                logerCore = _emptyLogerCore;
            }

            return logerCore;
        }

        /// <summary>
        /// 添加日志记录器
        /// </summary>
        /// <param name="logerCore">日志记录器</param>
        public static void AddLoger(ILogerCore logerCore)
        {
            if (logerCore == null)
            {
                return;
            }

            string logerName = logerCore.Name;
            if (string.IsNullOrEmpty(logerName))
            {
                if (_defaultLogerCore != null)
                {
                    _defaultLogerCore.Dispose();
                }

                _defaultLogerCore = logerCore;
            }
            else
            {
                _logerCoreDic.AddOrUpdate(logerName, logerCore, (key, oldValue) =>
                {
                    oldValue.Dispose();
                    return logerCore;
                });
            }
        }

        /// <summary>
        /// 移除日志记录器,移除成功返回true,否则返回false
        /// 移除后未调用Dispose方法,需要外部自行确定是否需要调用，此举可有利于对象的重复利用
        /// </summary>
        /// <param name="logerCore">日志记录器</param>
        /// <returns>移除成功返回true,否则返回false</returns>
        public static bool RemoveLoger(ILogerCore logerCore)
        {
            if (logerCore == null)
            {
                return false;
            }

            string logerName = logerCore.Name;
            if (string.IsNullOrEmpty(logerName))
            {
                _defaultLogerCore = _emptyLogerCore;
                return true;
            }
            else
            {
                ILogerCore oldLogerCore;
                return _logerCoreDic.TryRemove(logerName, out oldLogerCore);
            }
        }

        /// <summary>
        /// 清空所有日志记录器,包括默认
        /// </summary>
        public static void Clear()
        {
            foreach (ILogerCore logerCore in _logerCoreDic.Values)
            {
                logerCore.Dispose();
            }

            var defaultLoger = _defaultLogerCore;
            if (defaultLoger != _emptyLogerCore && defaultLoger != null)
            {
                defaultLoger.Dispose();
            }

            _defaultLogerCore = _emptyLogerCore;
            _logerCoreDic.Clear();
        }

        /// <summary>
        /// 释放日志资源
        /// </summary>
        public static void Release()
        {
            try
            {
                Clear();
                _defaultLogerCore = null;
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog(null, ex);
            }
        }
        #endregion



        #region 静态记录日志方法,默认日志快捷方法

        /// <summary>
        /// Loger添加日志的方法
        /// </summary>
        /// <param name="logItem">日志对象</param>
        public static void Log(LogItem logItem)
        {
            try
            {
                if (_logerCoreDic.Count > 0)
                {
                    foreach (ILogerCore logerCore in _logerCoreDic.Values)
                    {
                        logerCore.Log(logItem);
                    }
                }

                if (_defaultLogerCore != null)
                {
                    _defaultLogerCore.Log(logItem);
                }

                LogItem.Add(logItem);
            }
            catch (Exception exi)
            {
                LogSysInnerLog.OnRaiseLog(null, exi);
            }
        }



        #region Trace

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Trace(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Trace, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Trace(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Trace, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Trace(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Trace, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Trace(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Trace, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 追踪
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Trace(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Trace, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #region Debug

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Debug(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Debug, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Debug(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Debug, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Debug(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Debug, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Debug(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Debug, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 调试
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Debug(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Debug, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #region Info

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Info(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Info, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Info(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Info, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Info(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Info, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Info(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Info, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Info(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Info, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #region Warn

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Warn(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Warn, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Warn(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Warn, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Warn(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Warn, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Warn(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Warn, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Warn(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Warn, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #region Error

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Error(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Error, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Error(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Error, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Error(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Error, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Error(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Error, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Error(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Error, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #region Fatal

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Fatal(string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Fatal, LogConstant.DEFAULT_EVENT_ID, null, message, null);
            Log(item);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Fatal(int eventId, object tag, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Fatal, eventId, null, message, tag);
            Log(item);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Fatal(Exception ex, int eventId = LogConstant.DEFAULT_EVENT_ID, object tag = null, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Fatal, eventId, ex, null, tag);
            Log(item);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Fatal(Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Fatal, LogConstant.DEFAULT_EVENT_ID, ex, message, null);
            Log(item);
        }

        /// <summary>
        /// 致命
        /// </summary>
        /// <param name="eventId">事件ID</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="filePath">产生日志的代码文件</param>
        /// <param name="lineNum">产生日志在代码文件中的行数位置</param>
        /// <param name="memberName">产生日志的函数名</param>
        public static void Fatal(int eventId, object tag, Exception ex, string message, [CallerFilePath] string filePath = null, [CallerLineNumberAttribute] int lineNum = 0, [CallerMemberName] string memberName = null)
        {
            var item = LogItem.Take();
            item.Set(filePath, lineNum, memberName, DateTime.Now, Thread.CurrentThread, LogLevel.Fatal, eventId, ex, message, tag);
            Log(item);
        }

        #endregion

        #endregion
    }
}
